/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.debugger.debug; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import sun.tools.debug.RemoteClass; import sun.tools.debug.RemoteThread; import sun.tools.debug.RemoteField; import sun.tools.debug.RemoteObject; import sun.tools.debug.RemoteStackVariable; import sun.tools.debug.RemoteValue; import sun.tools.debug.RemoteStackFrame; import sun.tools.debug.RemoteArray; import org.openide.debugger.Watch; import org.openide.util.NbBundle; import org.netbeans.modules.debugger.support.AbstractVariable; import org.netbeans.modules.debugger.support.AbstractWatch; import org.netbeans.modules.debugger.support.AbstractThread; import org.netbeans.modules.debugger.support.util.Validator; import org.netbeans.modules.debugger.support.util.Protector; /** * Standart implementation of Watch interface. * @see org.openide.debugger.Watch * * @author Jan Jancura * @version 0.18, Feb 23, 1998 */ public class ToolsWatch extends AbstractWatch { /** generated Serialized Version UID */ static final long serialVersionUID = 3439367144447814302L; // private variables ..................................................... private ToolsVariable toolsVariable; protected transient boolean inScope = false; protected transient PropertyChangeSupport pcs; protected transient Validator validator; /** Name of watch like xxx.yyy [2]. */ protected String displayName; // init ..................................................................... /** * Non public constructor called from the JavaDebugger only. * User must create watch from Debugger.getNewWatch () method. */ ToolsWatch (ToolsDebugger debugger) { toolsVariable = new ToolsVariable (debugger, false); validator = debugger.getValidator (); init (); } private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { in.defaultReadObject (); validator = toolsVariable.getDebugger().getValidator (); init (); } // AbstractWatch implementation ......................................................... /** * Returns the name of this watch. * * @return the name of this watch. */ public String getVariableName () { return displayName; } /** * Destroys the watch. Removes it from the list of all watches in the system. */ public void remove () { toolsVariable.getDebugger().removeWatch (this); } /** * Sets variable name of this watch. * * @param name The name of variable of this watch. */ public void setVariableName (String displayName) { String old = this.displayName; this.displayName = displayName; validate (); } /** Getter to test if the property is "hidden". If a property is hidden it * is not presented in the list of all properties. Such a property can be used * for private usage of the IDE, not displaying anything to user. * <P> * To create hidden watch, use <CODE>Debugger.createWatch ("name", true)</CODE> method. * * @return true if the watch is hidden, false otherwise */ public boolean isHidden () { Watch[] w = toolsVariable.getDebugger().getWatches (); int i, k = w.length; for (i = 0; i < k; i++) if (w [i] == this) return false; return true; } // other methods ...................................................................... /** * Returns true if this variable is in scope. * * @return true if this variable is in scope. */ public boolean isInScope () { return inScope; } /** * Create AbstractVariable object for this Watch. Can return null, if this Watch currently not * represents valide variable. * * @return AbstractVariable object for this class. */ public AbstractVariable getVariable () { return (AbstractVariable) clone (); } /** * Returns true if this variable hasn't any fields. * * @return True if this variable hasn't any fields. */ public boolean isLeaf () { return false; } public boolean equals (java.lang.Object o) { return hashCode () == o.hashCode (); } public int hashCode () { return System.identityHashCode (this); } /** * Checks value of this watch and if is valide, and sets it. */ public void validate () { if ((toolsVariable.getDebugger ().synchronizer == null) || ( toolsVariable.getDebugger ().getState () == toolsVariable.getDebugger ().DEBUGGER_NOT_RUNNING ) ) { setError (NbBundle.getBundle (ToolsWatch.class).getString ("EXC_No_session")); firePropertyChange (null, null, null); } else if (toolsVariable.getDebugger().getState () != toolsVariable.getDebugger().DEBUGGER_STOPPED) { setError (NbBundle.getBundle (ToolsWatch.class).getString ("CTL_No_context")); firePropertyChange (null, null, null); } else { ToolsThread tt = (ToolsThread) toolsVariable.getDebugger().getCurrentThread (); if (tt != null) refreshValue (tt); else { setError (NbBundle.getBundle (ToolsWatch.class).getString ("CTL_No_context")); firePropertyChange (null, null, null); } } } /** * @return true if debugger is stopped. */ public boolean canValidate () { int state = toolsVariable.getDebugger().getState (); return (state == ToolsDebugger.DEBUGGER_STOPPED) || (state == ToolsDebugger.DEBUGGER_NOT_RUNNING); } /** * @return false, watch cannot be removed from validator when debugger is finished */ public boolean canRemove () { return false; } /** * Refresh value of watch in given context. */ void refreshValue (final ToolsThread tt) { toolsVariable.setErrorMessage (null); new Protector ("ToolsWatch.refreshValue") { // NOI18N public Object protect () throws Exception { RemoteValue oldValue = toolsVariable.getRemoteValue (); RemoteThread rt = tt.getRemoteThread (); try { int i = displayName.lastIndexOf ('.'); if (i >= 0) { RemoteClass clazz = getRemoteClass (displayName.substring (0, i)); if (clazz != null) { readStaticVariable (clazz, displayName.substring (i + 1, displayName.length ())); } } else if (!readLocalVariable (rt)) if (!readObjectVariable (rt)) if (!readStaticVariable (rt)) setErrorHelper (NbBundle.getBundle (ToolsWatch.class).getString ("CTL_Name_unknown")); } catch (Throwable e) { if (e instanceof ThreadDeath) throw (ThreadDeath)e; setErrorHelper (e.toString ()); // toolsVariable.setNull (); //value = e.toString (); } return null; } }.wait (toolsVariable.getDebugger().synchronizer, toolsVariable.getDebugger().killer); // deadlock prevention firePropertyChange (null, null, null); } public void refresh (AbstractThread t) { refreshValue ((ToolsThread)t); } private boolean readLocalVariable (RemoteThread rt) throws Exception { RemoteStackVariable variable = getRemoteStackVariable (rt, displayName); if (variable == null) return false; // unknown variable inScope = variable.inScope (); toolsVariable.update ( displayName, variable.getValue (), variable.getType ().toString () ); return true; } private boolean readObjectVariable (RemoteThread rt) throws Exception { RemoteStackVariable variable = getRemoteStackVariable (rt, "this"); // NOI18N if (variable == null) return false; // I'am in static method RemoteValue thisValue = variable.getValue (); if ((thisValue == null) || (!thisValue.isObject ())) return false; //Illegal state return toolsVariable.update ( ((RemoteObject) thisValue).getField (displayName), (RemoteObject) thisValue ); } private boolean readStaticVariable (RemoteThread rt) throws Exception { RemoteStackFrame frame = rt.getCurrentFrame (); if (frame == null) return false; RemoteClass clazz = frame.getRemoteClass (); if (clazz == null) return false; //??? return readStaticVariable (clazz, displayName); } private boolean readStaticVariable (RemoteClass clazz, String displayName) throws Exception { RemoteField remoteField; RemoteObject parentObject = null; try { remoteField = clazz.getField (displayName); if (remoteField == null) return false; toolsVariable.setRemoteValue (clazz.getFieldValue (displayName)); } catch (NoSuchFieldException e) { // to have transparent behaviour return false; // unknown variable } toolsVariable.update (remoteField, clazz); return true; } /** * Returns RemoteStackVariable for the name specified or null. * * @return RemoteStackVariable for the name specified or null. */ /* RemoteStackVariable getRemoteStackVariable (final String variableName) throws Exception { ToolsThread tt = (ToolsThread) debugger.getCurrentThread (); if (tt == null) return null; return getRemoteStackVariable (tt, variableName); }*/ /** * Returns RemoteStackVariable for the name specified or null. * * @return RemoteStackVariable for the name specified or null. */ private RemoteStackVariable getRemoteStackVariable ( RemoteThread rt, String variableName ) throws Exception { RemoteStackFrame frame = rt.getCurrentFrame (); if (frame == null) return null; return frame.getLocalVariable (variableName); } /** * Returns currently debugged RemoteClass or null. * * @return currently debugged RemoteClass or null. */ private RemoteClass getRemoteClass (final String className) throws Exception { if (toolsVariable.getDebugger().remoteDebugger == null) return null; return toolsVariable.getDebugger().remoteDebugger.findClass (className); } /** * Sets error message for this watch. */ void setErrorHelper (String description) { setError (description); } protected void init () { if (validator != null) validator.add (this); pcs = new PropertyChangeSupport (this); } // Delegating methods for ToolsVariable instance .................................. // Methods from ToolsVariable /** * Delegating method for ToolsVariable instance */ public void setAsText (final String value) { toolsVariable.setAsText (value); } /** * Delegating method for ToolsVariable instance */ public AbstractVariable[] getFields () { return toolsVariable.getFields (); } void setValue (String v) { toolsVariable.setValue (v); } // methods from VariableImpl protected java.lang.Object clone () { return toolsVariable.clone_protected (); } public String getAsText () { return toolsVariable.getAsText (); } public String getType () { return toolsVariable.getType (); } public synchronized void addPropertyChangeListener (PropertyChangeListener listener) { pcs.addPropertyChangeListener (listener); } public synchronized void removePropertyChangeListener (PropertyChangeListener listener) { pcs.removePropertyChangeListener (listener); } protected void firePropertyChange (String s, Object o, Object n) { pcs.firePropertyChange (s, o, n); } public String getInnerType () { return toolsVariable.getInnerType (); } public boolean isObject () { return toolsVariable.isObject (); } public boolean isArray () { return toolsVariable.isArray (); } public String getModifiers () { return toolsVariable.getModifiers (); } public String getErrorMessage () { return toolsVariable.getErrorMessage (); } protected void setError (String description) { toolsVariable.setError_protected (description); } public String toString () { return toolsVariable.toString (); } } /* * Log * 15 Gandalf-post-FCS1.13.4.0 3/28/00 Daniel Prusa * 14 Gandalf 1.13 1/13/00 Daniel Prusa NOI18N * 13 Gandalf 1.12 1/10/00 Jan Jancura Refresh of locales * updated * 12 Gandalf 1.11 12/30/99 Daniel Prusa Validator placed into * Watch * 11 Gandalf 1.10 12/21/99 Daniel Prusa Interfaces Debugger, * Watch, Breakpoint changed to abstract classes. * 10 Gandalf 1.9 11/8/99 Jan Jancura Somma classes renamed * 9 Gandalf 1.8 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 8 Gandalf 1.7 9/15/99 Jan Jancura * 7 Gandalf 1.6 7/30/99 Jan Jancura * 6 Gandalf 1.5 7/21/99 Jan Jancura * 5 Gandalf 1.4 6/10/99 Jan Jancura * 4 Gandalf 1.3 6/9/99 Jan Jancura * 3 Gandalf 1.2 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 2 Gandalf 1.1 6/4/99 Jan Jancura * 1 Gandalf 1.0 6/1/99 Jan Jancura * $ */